<cfcomponent>

	<!--- <cfset variables.sessionFactory = Application.hibernateConfig.buildSessionFactory()> --->
	
	<cfset  variables.typeKey = "$type$">
	
	<cffunction name="getSession" access="private" returntype="any" output="false">
		<cfset var sessionFactory = Application.hibernateConfig.buildSessionFactory()>
		<cfset var mySession = sessionFactory.openSession()>
		<cfset var EntityMode = createObject("java", "org.hibernate.EntityMode")>
		<cfset mySession = mySession.getSession(EntityMode.MAP)>
		<cfreturn mySession>
	</cffunction>
	
	<cffunction name="saveOrUpdate" returntype="void" access="private" output="false">
		<cfargument name="theObj" type="any" required="true">
		<cfset var sessionFactory = Application.hibernateConfig.buildSessionFactory()>
		<cfset var mySession = sessionFactory.openSession()>
		<cfset var EntityMode = createObject("java", "org.hibernate.EntityMode")>
		<cfset var tx = 0>
		<cfset var id = 0>
		<cfset mySession = mySession.getSession(EntityMode.MAP)>
		<cfset tx = mySession.beginTransaction()>
		<!--- <cfdump var="#arguments.theObj.toString()#" label="theObj"><cfabort> --->
		<!--- <cfdump var="#mySession#" label="mySession"><cfabort> JavaCast("string", theObj["type"]),  --->
		<cfif theObj["id"] eq 0>
			<cfset id = mySession.save(theObj)>
			<cfset theObj["id"] = id>
		<cfelse>
			<cfset mySession.saveOrUpdate(theObj)>
		</cfif>
		<cfset tx.commit()>
		<cfset mySession.close()>
		<cfset sessionFactory.close()>
	</cffunction>
	
	<cffunction name="mapToCFC" returntype="any" access="private" output="false">
		<cfargument name="data" type="struct" required="true">
		<cfset var key = 0>
		<cfset var element = 0>
		<cfset var array = 0>
		<cfset var result = 0>
		<cfset var resultData = structNew()>
		<cfset var theSet = 0>
		<cfset var iterator = 0>
		<cfset var typeKey = "$type$">
		<cfloop collection="#data#" item="key">
			<cfif isDefined("data.#key#")>
				<cfif data[key].getClass().getName() neq "org.hibernate.collection.PersistentSet"
					AND data[key].getClass().getName() neq "org.hibernate.collection.PersistentBag"
					AND data[key].getClass().getName() neq "org.hibernate.collection.PersistentIdentifierBag">
					<cftrace text="data[key].getClass().getName() = #data[key].getClass().getName()#">
					<cfif data[key] neq "">
						<cfset resultData[key] = data[key]>
					<cfelse>
						<cfset resultData[key] = "">
					</cfif>
				<cfelse>
					<cfset array = arrayNew(1)>
					<cfset theset = data[key]> 
					<cfset iterator = theSet.iterator()>
					<cfloop condition="#iterator.hasNext()#">
						<cfset element = iterator.next()>
						<cfif isStruct(element)>
							<cfset arrayAppend(array, mapToCFC(element))>
						<cfelse>
							<cfset arrayAppend(array, element)>
						</cfif>
					</cfloop>
					<cfset resultData[key] = array>
				</cfif>
			</cfif>
		</cfloop>
		<cfset result = createObject("component", data[variables.typeKey]).init(argumentCollection=resultData)>
		<cfreturn result>
	</cffunction>
	
	<cffunction name="mapToHashMap" returntype="struct" access="public" output="false">
		<cfargument name="result" type="any" required="true" />
		<cfset var hashMap = CreateObject("java", "java.util.HashMap").init()>
		<cfset var props = result.getTO()>
		<cfset var sessionFactory = Application.hibernateConfig.buildSessionFactory()>
		<cfset var hibMetaData = sessionFactory.getClassMetaData(getMetaData(result).name)>
		<cfset var prop = 0>
		<cfset var i = 0>
		<cfset var hashSet = 0>
		<cftrace text="new hashMap">
		<cfloop list="#structKeyList(props)#" index="prop">
			<cfif isObject(evaluate('props.#prop#'))>
				<cftrace text="hasMap.put('#prop#', mapToHashMap('props.#prop#'))">
				<cfset hashMap.put(prop, mapToHashMap(evaluate('props.#prop#')))>
			<cfelseif isArray(evaluate('props.#prop#'))>
				<!--- <cfset hashMap["#prop#"] = createObject("java", "java.util.ArrayList").init()> --->
				<cfset hashSet = createObject("java", "java.util.HashSet").init()>
				<cftrace text="new hashSet">
				<cfloop from="1" to="#arrayLen(evaluate('props.#prop#'))#" index="i">
					<cfif isObject(evaluate('props.#prop#[#i#]'))>
						<cftrace text="hashSet.add(mapToHashMap('props.#prop#[#i#]')))">
						<cfset hashSet.add(mapToHashMap(evaluate('props.#prop#[#i#]')))>
					<cfelse>
						<cfset hashSet.add(evaluate('props.#prop#[#i#]'))>
						<cftrace text="hashSet.add('props.#prop#[#i#]')))">
					</cfif>
				</cfloop>
				<cfset hashMap.put(prop, hashSet)>
				<cftrace text="hasMap.put('#prop#', hashSet)">
			<cfelseif getPropertyType(prop, hibMetaData) eq "integer">
				<cfset hashMap.put(prop, createObject("java", "java.lang.Integer").init(evaluate('props.#prop#')))> 
				<cftrace text="hasMap.put('#prop#', (Integer) #evaluate('props.#prop#')#)">
			<cfelse>
				<cfset hashMap.put(prop, JavaCast("string", evaluate('props.#prop#')))>
				<cftrace text="hasMap.put('#prop#', (String) #evaluate('props.#prop#')#)">
			</cfif>
		</cfloop>
		<cfset hashMap.put(variables.typeKey, JavaCast("string", getMetaData(result).name))>
		<cftrace text="hasMap.put('type', (String) #getMetaData(result).name#)">
		<cfreturn hashMap>
	</cffunction>

	<cffunction name="getPropertyType" access="private" returntype="string" output="false">
		<cfargument name="propertyname" type="string" required="true">
		<cfargument name="hibMetaData" type="any" required="true">
		<cfset var type = "">
		<cftry>
			<cfset type = hibMetaData.getPropertyType(arguments.propertyname).getName()>
			<cfcatch type="any">
				<cfset type = hibMetaData.getIdentifierType().getName()>
			</cfcatch>
		</cftry>
		<cfreturn type>
	</cffunction>

</cfcomponent>